import { Render } from "./Render";
import { Webgl2DTextureSimple } from "./Webgl2DTextureSimple";

/*
 * @Author: Snow
 * @Date: 2021-09-08 12:01:51
 * @Description: 特殊图像处理
 */
export class Webgl2DTextureSimple2 extends Webgl2DTextureSimple{
    
    public uKernelLoc:WebGLUniformLocation;

    public uKernelWeightLoc:WebGLUniformLocation;

    public override initUITools():void{
        // Setup a ui.
        this.createTabel("sharpness");
        this.createTabel("ggogogogog");
        this.loadImage(null);
    }

    public override initGLSL():void{
        this.vsSource = `
            attribute vec2 aPosition;
            attribute vec2 aTexCoord;
            attribute vec4 aPosColor;

            uniform vec2 uResolution;
            uniform mat4 uModelViewMatrix;
            uniform mat4 uProjectionMatrix;
            uniform mat4 uViewMatrix;

            varying mediump vec2 vTexCoord;
            varying mediump vec4 vPosColor;

            void main() {
                // 从像素坐标转换到 0.0 到 1.0
            vec2 zeroToOne = aPosition / uResolution;
        
            // 再把 0->1 转换 0->2
            vec2 zeroToTwo = zeroToOne * 2.0;
        
            // 把 0->2 转换到 -1->+1 (裁剪空间)
            vec2 clipSpace = zeroToTwo - 1.0;
        
            gl_Position = vec4(clipSpace * vec2(1,-1), 0, 1);
            vTexCoord = aTexCoord;
            vPosColor = aPosColor;
            }
        `;
        
        this.fsSource = `
            
            // 纹理
            precision mediump float;
            uniform sampler2D uImage;

            //纹理size
            uniform vec2 uSize;
            //内卷数组
            uniform float uKernel[9];
            //权重
            uniform float uKernelWeight;
            
            varying mediump vec2 vTexCoord;
            varying mediump vec4 vPosColor;

            void main() {
                
                // 计算1像素对应的纹理坐标
                vec2 onePixel = vec2(1.0, 1.0) / uSize;
                float a;
                if(uSize.x > 0.0){
                    a = 1.0;
                }
                vec4 colorSum =
                texture2D(uImage, vTexCoord + onePixel * vec2(-1.0, -1.0)) * uKernel[0] +
                texture2D(uImage, vTexCoord + onePixel * vec2( 0.0, -1.0)) * uKernel[1] +
                texture2D(uImage, vTexCoord + onePixel * vec2( 1.0, -1.0)) * uKernel[2] +
                texture2D(uImage, vTexCoord + onePixel * vec2(-1.0,  0.0)) * uKernel[3] +
                texture2D(uImage, vTexCoord + onePixel * vec2( 0.0,  0.0)) * uKernel[4] +
                texture2D(uImage, vTexCoord + onePixel * vec2( 1.0,  0.0)) * uKernel[5] +
                texture2D(uImage, vTexCoord + onePixel * vec2(-1.0,  1.0)) * uKernel[6] +
                texture2D(uImage, vTexCoord + onePixel * vec2( 0.0,  1.0)) * uKernel[7] +
                texture2D(uImage, vTexCoord + onePixel * vec2( 1.0,  1.0)) * uKernel[8] ;
 
                // 只把rgb值求和除以权重
                // 将阿尔法值设为 1.0
                gl_FragColor = vec4((colorSum / uKernelWeight).rgb, 1.0);
            }
            `;
    }

    public override initProgramInfo():any{
        this.aPositionLoc = this.gl.getAttribLocation(this.shaderProgram,"aPosition");
        
        this.aPosColorLoc = this.gl.getAttribLocation(this.shaderProgram,"aPosColor");

        this.aTexCoordLoc = this.gl.getAttribLocation(this.shaderProgram,"aTexCoord");
        
        this.uResolutionLoc = this.gl.getUniformLocation(this.shaderProgram,"uResolution");

        this.uImageLoc = this.gl.getUniformLocation(this.shaderProgram,"uImage");
        
        this.uSizeLoc = this.gl.getUniformLocation(this.shaderProgram,"uSize");
        
        ////数组获取地址  用第一个数组元素地址
        this.uKernelLoc = this.gl.getUniformLocation(this.shaderProgram,"uKernel[0]");

        this.uKernelWeightLoc = this.gl.getUniformLocation(this.shaderProgram,"uKernelWeight");
        
        return null;
    }

    protected createAndSetupTexture():WebGLTexture {
        const gl = Render.GL;
        const texture = gl.createTexture();
        gl.bindTexture(gl.TEXTURE_2D, texture);
        // 设置材质，这样我们可以对任意大小的图像进行像素操作
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
        return texture;
    }

    private computeKernelWeight(kernel:number[]):number {
        let weight = kernel.reduce(function(prev, curr) {
            return prev + curr;
        });
        return weight <= 0 ? 1 : weight;
    }

    public override draw():void{
        const gl = this.gl;
        gl.viewport(0,0,gl.canvas.width,gl.canvas.height);
        gl.clearColor(1,1,1,1);
        gl.clearDepth(1.0);
		gl.enable(gl.DEPTH_TEST);
		gl.depthFunc(gl.LEQUAL);
		gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

        const pos:number[] = [
            100,100,
            200,100,
            200,200,
            100,200,
        ];

        const posBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER,posBuffer);
        gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(pos),gl.STATIC_DRAW);
        gl.enableVertexAttribArray(this.aPositionLoc);
        {
            gl.vertexAttribPointer(this.aPositionLoc,2,gl.FLOAT,false,0,0);
        }

        //纹理坐标
        const texPos:number[] = [
            0,0,
            1,0,
            1,1,
            0,1
        ];

        const texBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER,texBuffer);
        gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(texPos),gl.STATIC_DRAW);
        gl.enableVertexAttribArray(this.aTexCoordLoc);
        {
            gl.vertexAttribPointer(this.aTexCoordLoc,2,gl.FLOAT,false,0,0);
        }

        // 创建纹理
        if(this.textrue && this.texImage){
            //this.textrue = gl.createTexture();
            gl.bindTexture(gl.TEXTURE_2D, this.textrue);
            // 设置参数，让我们可以绘制任何尺寸的图像
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    
            // 将图像上传到纹理
            //if(this.texImage)
            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.texImage);
        }
        

        // 创建两个纹理绑定到帧缓冲
        // let textures = [];
        // let framebuffers = [];
        // for (let ii = 0; ii < 2; ++ii) {
        //     if(!this.texImage)break;
        //     let texture = this.createAndSetupTexture();
        //     textures.push(texture);
        
        //     // 设置纹理大小和图像大小一致
        //     gl.texImage2D(
        //         gl.TEXTURE_2D, 0, gl.RGBA, this.texImage.width, this.texImage.height, 0,
        //         gl.RGBA, gl.UNSIGNED_BYTE, null);
        
        //     // 创建一个帧缓冲
        //     var fbo = gl.createFramebuffer();
        //     framebuffers.push(fbo);
        //     gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
        
        //     // 绑定纹理到帧缓冲
        //     gl.framebufferTexture2D(
        //         gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
        // }

        if(this.textrue){
            //使用纹理
            gl.uniform1i(this.uImageLoc, 0);
            gl.activeTexture(gl.TEXTURE0);
            gl.bindTexture(gl.TEXTURE_2D,this.textrue);
        }

        //顶点
        const indexs = [
            0,1,2,2,3,0
        ];

        const indexsBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indexsBuffer);
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,new Uint16Array(indexs),gl.STATIC_DRAW);


        gl.useProgram(this.shaderProgram);

        const resolution:number[] = [
            gl.canvas.width,gl.canvas.height,
        ]

        gl.uniform2fv(this.uResolutionLoc,new Float32Array(resolution));
        
        let red = this.uiParam["red"];
        let green = this.uiParam["green"];
        let blue = this.uiParam["blue"];
        let alpha = this.uiParam["alpha"];

        gl.uniform4fv(this.uColorLoc,new Float32Array([red,green,blue,alpha]));

        if(this.texImage)
        gl.uniform2f(this.uSizeLoc,this.texImage.width,this.texImage.height);
       
        let edgeDetectKernel = [
            -5, 0, 0,
            0, 0, 0,
            0, 0, 5
        ];
        gl.uniform1fv(this.uKernelLoc, edgeDetectKernel);
        gl.uniform1f(this.uKernelWeightLoc, this.computeKernelWeight(edgeDetectKernel)); 

        //gl.drawArrays(gl.TRIANGLES,0,6);
        gl.drawElements(gl.TRIANGLES,6,gl.UNSIGNED_SHORT,0);
    }


    
}
